﻿#include "udpServer.h"
#include <QDebug>
#include <QDateTime>
#include <QSqlQuery>
#include <QSqlError>
#include <QSqlDatabase>

UdpServer::UdpServer(QObject *parent)
    : QObject(parent), udpSocket(this)
{
    if (udpSocket.bind(8855) == false) {
        exit(1);
    }
    //client = "192.168.1.103";
    qDebug() << "Udp Server running";
    connect(&udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
}

UdpServer::~UdpServer()
{
}
int UdpServer::valist2array(QByteArray &arr, QVariant &data)
{
    QVariantList list = data.toList();
    foreach (const QVariant &v, list) {
        arr.append((char)v.toInt());
    }
    return 0;
}
int UdpServer::array2valist(QVariant &data, QByteArray &arr)
{
    QVariantList list;
    foreach (const unsigned char &v, arr) {
        list.append(v);
    }
    data = QVariant(list);
    return 0;
}
void UdpServer::readPendingDatagrams()
{
    mysql_init();
    while (udpSocket.hasPendingDatagrams()) {
        QHostAddress sender;
        quint16 senderPort;
        QByteArray datagram;
        QVariant data;
        unsigned short crc, crc1 ;
        //QByteArray array;
        datagram.resize(udpSocket.pendingDatagramSize());
        udpSocket.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        qDebug() << "ip " << sender << "port " << senderPort;
        qDebug() << "datagram " << datagram;
        crc = usCRC16(datagram, datagram.size() - 2);
        crc1 = ((quint16)datagram[datagram.size() - 2] << 8);
        crc1 |= (quint8)datagram[datagram.size() - 1];
        //crc1 = datagram[datagram.size() - 2] | (datagram[datagram.size() - 1] << 8);
        if (crc != crc1) {
            continue;
        }
        mysql_table(datagram);
        array2valist(data, datagram);
        //QString addr = sender.toString() + ":" + QString::number(senderPort);
        //array2string(lockId, array);
        emit lockStatusChanged(data, sender.toString(), senderPort);
    }
    return;
}
unsigned short UdpServer::crc16_update(unsigned short crc, unsigned char a)//在函数usCRC16内部调用
{
    int i;
    crc^=a;
    for(i=0;i<8;++i)
    {
        if(crc&1)
        crc=(crc>>1)^0xA001;
        else
        crc=(crc>>1);
    }
    return crc;
}
unsigned short UdpServer::usCRC16(const char *pucFrame, int usLen)
{
    unsigned int crc_temp=0xffff;
        unsigned int x;
        while(usLen)
        {
            crc_temp=crc16_update(crc_temp, *pucFrame++);
            --usLen;
        }
        x = crc_temp>>8;//处理CRC数据，调换高低位
        crc_temp = crc_temp<<8;
        crc_temp = crc_temp+x;
        return crc_temp;//注意：CRC值高低位已调换，高位对应高位，低位对应低位
}
void UdpServer::sendCommand(QVariant lockID, char index, char cmd, QVariant data, QString sender, int port)
{
    //QString &addr = client;
    //QHostAddress sender(addr);
    qint16 len;
    QByteArray buf;
    QByteArray id;
    qint16 crc;
    int ret, retId;
    ret = valist2array(buf, data);
    retId = valist2array(id, lockID);
    if (ret < 0 || retId < 0) {
        return;
    }
    len = buf.length();
    buf.prepend(len);
    buf.prepend(cmd);
    buf.prepend(index);
    buf.prepend(id);
    crc = usCRC16(buf, buf.length());
    buf.append((crc & 0xff00) >> 8);
    buf.append(crc & 0xff);
    qDebug() << "UdpServer write: " << buf;
    udpSocket.writeDatagram(buf, QHostAddress(sender), port);
    return;
}

void UdpServer::mysql_init()
{
    QSqlError err;
    //打开MySQL
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("127.0.0.1");  //设置主机地址
    db.setPort(3306);  //设置端口
    db.setDatabaseName("demo_xfs");  //设置数据库名称
    db.setUserName("root");  //设置用户名
    db.setPassword("tjbus01");  //设置密码
    // 打开数据库
    if (!db.open()) {
        qDebug()<<"failed to connect to mysql";
        err = db.lastError();
    }
}
void UdpServer::mysql_table(QByteArray data)
{
    QSqlQuery query;
    bool success;
    success = query.prepare("INSERT INTO demo_xfs (posid, water, turn, position_x, position_y, electricity, network, progVer, binVer, IMEI, IMSI, working, date)"
                            "VALUE(:posid, :water, :turn, :position_x, :position_y, :electricity, :network, :progVer, :binVer, :IMEI, :IMSI, :working, :date)");
    if (!success) {
        qDebug()<<"failed";
    }
    query.bindValue(":posid", QString::asprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                                             data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]));
    if (data[15] & 1) {
        query.bindValue(":water", 1);
    } else {
        query.bindValue(":water", 0);
    }
    if (data[15] & 2) {
        query.bindValue(":turn", 1);
    } else {
        query.bindValue(":turn", 0);
    }
    query.bindValue(":position_x", "0.0");
    query.bindValue(":position_y", "0.0");
    query.bindValue(":electricity", QString::asprintf("%d", (data[16] << 8) | data[17]));
    query.bindValue(":network", 0);
    query.bindValue(":progVer", "0");
    query.bindValue(":binVer", "0");
    query.bindValue(":IMEI", "0");
    query.bindValue(":IMSI", "0");
    query.bindValue(":working", 0);
    query.bindValue(":date", "2018-1-18 15:42:00");
}
